Related
Please share the working code for repeatbox in smartface.
I have been testing all the possibilities but non have worked yet, I wish to show the data from the database on the repeatbox. I am able to get the data but real problem occurs when I want to show the respective page on each item click.
below is the test code which I am using in callback function to show the retrieved test data on the repeatbox.
function Listalluser_callBack(ul) {
var userdata = ul.split("|");
for (var i = 0; i < userdata.length - 1; i++) {
var rowdata = userdata[i].split(",");
var productsObj = {}
productsObj.Id = rowdata[0];
productsObj.Username = rowdata[1];
productsObj.Password = rowdata[2];
productsData.push(productsObj);
}
var lbl = new SMF.UI.Label({
top : "0%",
left : "0%",
width : "10%",
height : "100%",
fillColor : "#FFFFFF",
textAlignment : SMF.UI.TextAlignment.cente
});
var lbl1 = new SMF.UI.Label({
top : "0%",
left : "10%",
width : "70%",
height : "100%",
fillColor : "#FFFFFF",
textAlignment : SMF.UI.TextAlignment.center
});
var imgbtn = new SMF.UI.ImageButton({
top : "0%",
left : "80%",
height : "100%",
width : "20%"
});
var repeatBox1 = new SMF.UI.RepeatBox({
width : "100%",
height : "95%",
left : "0%",
top : "0%",
showScrollbar : true,
fillColor : "white",
backgroundTransparent : true
});
imgbtn.defaultImage = "ic_action_next_item.png";
//imgbtn.text = "";
imgbtn.onTouch = function (e) {
// alert(imgbtn.text);
alert(repeatBox1.controls[2].text);
}
repeatBox1.dataSource = productsData;
repeatBox1.onRowRender = function (e) {
this.controls[0].text = productsData[e.rowIndex].Id;
this.controls[1].text = productsData[e.rowIndex].Username;
this.controls[2].text = productsData[e.rowIndex].Id;
};
repeatBox1.onSelectedItem = function (e) {
alert("Selected " + (e.rowIndex + 1) + ". row");
};
repeatBox1.onRowDeleting = function (e) {
if (e.rowIndex === 0) {
alert("first row is deleted...");
}
};
repeatBox1.autoSize = true;
repeatBox1.itemTemplate.height = Device.screenHeight / 8;
repeatBox1.itemTemplate.add(lbl);
repeatBox1.itemTemplate.add(lbl1);
repeatBox1.itemTemplate.add(imgbtn);
repeatBox1.layoutType = SMF.UI.LayoutType.linear;
repeatBox1.horizontalGap = 5;
//repeatBox1.groupItems = true;
repeatBox1.useActiveItem = true;
Pages.pgHome.add(repeatBox1);
}
Any other sample code which can be used to show the respective page depending upon the condition for example as below depending on id i have to show his profile on the other page.
Thanks in advance.
To change a page according to a pressed row, you can use the onSelectedItem function.
repeatboxReference.onSelectedItem = function(e){
switch(e.rowIndex){
case 0:
Pages.Page1.show(/*params*/);
break;
case 1:
Pages.Page2.show(/*params*/);
break;
//And so on
}
};
You should refresh your repeatbox and also use repeatBox1.show(); to show the box
I'm stuck trying to get a very simple task to work on my app. Essentially, I want to be able to add view to a ScrollView when users click a button. Let's call this first view added a "Card". Inside this card, I also have another scrollview which is supposed to then dynamically receive and display "categories" views.
For the most part everything is working fine: when the "Add" button at the top is clicked, the "card" is created and I am able to see all of the information, HOWEVER, the problem is that each time I "Add" a card, I end up not only adding "categories" views to the current created card by a factor of 2, but also the same happens to the previously added cards. Like the following:
I hope this makes sense.
Here's my code (my button event listener):
addViewButton.addEventListener('click', function(e) {
var url = "https://my.apilink.com";
var xhr = Titanium.Network.createHTTPClient();
xhr.open('GET', url);
xhr.onload = function() {
var response = JSON.parse(this.responseText);
var t = response.data.categories;
var bons = [];
for (var item in t) {
bons.push(t[item]);
}
Ti.API.info("Data received" + bons);
var resp = {
response : bons
};
createCard(resp);
};
xhr.send();
}
And here's where it all happens (creating the views (cards)):
var catScrollView = Titanium.UI.createScrollView({
top : 130,
left : 0,
right : 0,
contentWidth : '100%',
showHorizontalScrollIndicator : false,
showVerticalScrollIndicator : true,
});
var scrollView = Ti.UI.createScrollView({
top : 130,
left : 0,
right : 0,
backgroundColor : 'white',
contentWidth : '100%',
showHorizontalScrollIndicator : false,
showVerticalScrollIndicator : true,
});
var topPosition = 20;
var leftPosition = 20;
var topPositionCat = 30;
var i = 0;
function createCard(_args) {
var response = _args.response;
Ti.API.info("Response" + response);
var colorArr = ["red", "orange", "blue", "green", "pink", "yellow"];
var fakeArray = ["card 0", "card 1", "card 2", "card 3"];
var ranIndex = getRandom(colorArr.length);
i++;
for (var d = 0; d < response.length; d++) {
var panelImage = Ti.UI.createView({
backgroundColor : colorArr[ranIndex],
top : topPosition + (i * 60),
borderRadius : 5,
borderColor : 'white',
borderWidth : 2,
id : i,
bit : false,
active : false,
height : 350,
width : 290,
});
//add a few attributes to the card
var cardTitle = Ti.UI.createLabel({
text : "I am card # " + i,
top : 10,
left : 0,
color : 'black'
});
panelImage.add(cardTitle);
//Add the EventListener for the view.
panelImage.addEventListener('singletap', cardButtonHandler);
//Add scrollview and a card here
var leftPosition = 20;
if (d % 2 == 0) {
leftPosition = 20;
} else {
leftPosition = 180;
}
var panelImageCat = Ti.UI.createView({
backgroundImage : '/images/row_bg.png',
top : topPositionCat,
left : leftPosition,
height : 100,
width : 100,
});
var catImageButton = Ti.UI.createImageView({
image : response[d].icon,
name : response[d].name,
id : response[d].id,
icon : response[d].icon,
width : 90,
height : 90,
top : 4
});
panelImageCat.add(catImageButton);
var catName = Ti.UI.createLabel({
text : response[d].name,
textAlign : 'center',
color : 'black',
top : 3,
font : {
fontWeight : 'bold'
}
});
panelImageCat.add(catName);
if (leftPosition == 180) {
topPositionCat += panelImageCat.height + 10;
}
// add the view in scroll view
catScrollView.add(panelImageCat);
panelImage.add(catScrollView);
// Add the EventListener for the view.
catImageButton.addEventListener('click', function(e) {
alert(e.source.name);
});
}// END FOR LOOP
catScrollView.contentHeight = topPositionCat + 20;
// add the view in scroll view
scrollView.add(panelImage);
}
Of course there's more code for when users tap on each "card" etc. But that's irrelevant.
This is probably very simple to solve. I suspect it has to do with how I am setting up the loops to create each card and its corresponded categories views etc.
Any help, guidance is highly appreciated.
Thank you!
I guess that the main problem of your code is the way you are adding cards to the row. You shouldn't add a card for each category, but only create a card, add each category to that card, and then, add the card to the parent scrollView.
Nevertheless, in order to improve the readability of your code (and thus, your capability to maintain it), you should consider doing two things :
Move all the code that concern styling inside a separated file.
Create "builders" to instantiate views components so that, your main code only contains relevant information.
Here is an example on TiFiddle, and right below, explanation about it.
Move styling in a separated file
Just make a really easy-to-use commonJS-like module. Titanium supports them, do not be shy.
styles.js
/* ------ Top Level Components ------ */
exports.mainWindow = {
backgroundColor: "#ffffff",
layout: "vertical"
};
exports.topLevelScrollView = {
width: Ti.UI.FILL,
height: Ti.UI.FILL,
contentWidth : '100%',
showHorizontalScrollIndicator : false,
showVerticalScrollIndicator : true
};
exports.addButton = {
width: Ti.UI.FILL,
backgroundColor: "#999999",
color: "#ffffff",
font: { fontSize: 14 },
height: 50
};
/* ------ Card ----*/
exports.cardContainer = {
borderRadius : 5,
borderColor : '#ffffff',
borderWidth : 2,
top: 0,
height : 350,
width : Ti.UI.FILL,
};
exports.cardTitle = {
top : 10,
left : 10,
height: Ti.UI.SIZE,
width: Ti.UI.FILL,
color : '#141414'
};
exports.cardScrollView = {
layout: "horizontal",
contentWidth : '100%',
showHorizontalScrollIndicator : false,
showVerticalScrollIndicator : true,
top: 50,
height: Ti.UI.SIZE,
width: Ti.UI.SIZE
};
/* ------ Category ------*/
exports.categoryContainer = {
backgroundColor: "#cccccc",
opacity: "0.8",
left: 30,
right: 30,
top: 10,
bottom: 10,
height : 100,
width : 100,
};
exports.categoryImage = {
width : 90,
height : 90,
top : 4
};
exports.categoryTitle = {
textAlign : 'center',
color : 'black',
top : 3,
font : {
fontWeight : 'bold'
}
};
/* TIPS: Always use fancy colors for your tests <3 */
exports.colors = [
"#c0392b",
"#e67e22",
"#3498db",
"#2ecc71",
"#9b59b6",
"#f1c40f"
];
Create also some utils
The way you are creating card and categories has nothing to go alongside the other function. So, let's create another module.
ui_utils.js
exports.pickColor = function (colors) {
var randomIndex = Math.floor(Math.random() * colors.length);
return colors[randomIndex];
};
/* Create and return a cardContainer that may hold several categoryContainers */
exports.createCardView = function (id, title, color, styles, listener) {
var cardContainer = Ti.UI.createView(styles.cardContainer),
cardTitle = Ti.UI.createLabel(styles.cardTitle),
cardScrollView = Ti.UI.createScrollView(styles.cardScrollView);
cardContainer.id = id;
cardContainer.bit = false;
cardContainer.active = false;
cardContainer.backgroundColor = color;
cardContainer.cardScrollView = cardScrollView;
cardTitle.text = title;
cardContainer.addEventListener(listener.eventName, listener.listener);
cardContainer.add(cardTitle);
cardContainer.add(cardScrollView);
return cardContainer;
};
/* Create and return a categoryContainer */
exports.createCategoryView = function (category, styles, listener) {
var categoryContainer = Ti.UI.createView(styles.categoryContainer),
categoryTitle = Ti.UI.createLabel(styles.categoryTitle),
categoryImage = Ti.UI.createImageView(styles.categoryImage);
categoryTitle.text = category.name;
categoryImage.id = category.id;
categoryImage.name = category.name;
categoryImage.image = category.icon;
categoryImage.addEventListener(listener.eventName, listener.listener);
categoryContainer.add(categoryTitle);
categoryContainer.add(categoryImage);
return categoryContainer;
};
Rewrite your main file
And finally, the main function with just the minimal amount of code.
app.js
/* Start by requiring defined modules, and creating different views */
var styles = require('styles'),
uiUtils = require('ui_utils'),
mainWindow = Ti.UI.createWindow(styles.mainWindow),
topLevelScrollView = Ti.UI.createScrollView(styles.topLevelScrollView),
addButton = Ti.UI.createButton(styles.addButton);
/* The famous one */
function createCard(_args) {
var response = _args.response;
Ti.API.info("Response :" + response);
/* Create the new card */
var id = topLevelScrollView.children.length, /* Ugly .. find another way */
title = "I am card #" + id,
color = uiUtils.pickColor(styles.colors),
listener = {
eventName: "singleTap",
listener: function () { } /* Just supply a listener */
},
cardContainer = uiUtils.createCardView(id, title, color, styles, listener);
cardContainer.top = 50 * id;
/* Iterate over each category that we have in response */
for (var i = 0, category; category = response[i]; i++) {
/* Create the category view */
var listener = {
eventName: "click",
listener: function(e) { alert(e.source.name); }
},
categoryContainer = uiUtils.createCategoryView(category, styles, listener);
/* Add it to the card scrollView */
cardContainer.cardScrollView.add(categoryContainer);
}
/* Dont forget to add the card to the topLevelScrollView */
topLevelScrollView.add(cardContainer);
}
/* Initialize the different views */
addButton.title = "ADD";
mainWindow.add(addButton);
mainWindow.add(topLevelScrollView);
mainWindow.open();
Enjoy!
here i am posting a jquery code which is working but few lines are not clear to me .
js fiddle link.
full code
HTML:
<form method="post" action="WebForm1.aspx" id="ctl00">
<input type="submit" name="Button1" value="Fly DIV" id="Button1" class="toggleUPSContainer" />
</form>
CSS:
#UPSContainer{
position: absolute;
display: none;
background:red;
height:0;
width:0;
}
javascript:
$(document).ready(function () {
var $els = [];
var data = {
"UPSContainer": {
"height" : 100,
"width" : 100
},
"isAnimating" : false
};
$els.window = $(window);
$els.form = $('#ctl00');
$els.toggleUPSButtons = $('.toggleUPSContainer');
function addUPSOverlay(){
$els.form.append('<div id="UPSContainer"></div>');
$els.UPSContainer = $('#UPSContainer');
}
function getNewWindowCorner(){
data.windowWidth = parseInt($els.window.width());
data.windowHeight = parseInt($els.window.height());
if($els.UPSContainer.is(':hidden')){
$els.UPSContainer.css({
top: data.windowHeight + 'px',
left: data.windowWidth + 'px'
});
}else{
$els.UPSContainer.css({
left: ((data.windowWidth - data.UPSContainer.width) / 2) + 'px',
top: ((data.windowHeight - data.UPSContainer.height) / 2) + 'px'
});
}
}
function containerOpenComplete(){
// do what you want here when opening complete
}
function containerCloseComplete(){
// do what you want here when closing complete
}
function toggleUPSOverlay(e){
e.preventDefault();
if(!data.isAnimating){
if($els.UPSContainer.is(':hidden')){ // currently closed so open
$els.UPSContainer.show();
$els.UPSContainer.animate({
left: ((data.windowWidth - data.UPSContainer.width) / 2) + 'px',
top: ((data.windowHeight - data.UPSContainer.height) / 2) + 'px',
height: data.UPSContainer.height + 'px',
width: data.UPSContainer.width + 'px'
}, 200, function(){
containerOpenComplete();
});
}else{ // currently open so close
$els.UPSContainer.animate({
left: data.windowWidth + 'px',
top: data.windowHeight + 'px',
height: 0 + 'px',
width: 0 + 'px'
}, 200,
function () {
$els.UPSContainer.hide();
containerCloseComplete();
});
}
}
}
function attachEvents(){
$els.window.on('resize', getNewWindowCorner);
$els.toggleUPSButtons.on('click', toggleUPSOverlay);
}
function initialize(){
addUPSOverlay();
getNewWindowCorner();
attachEvents();
}
initialize();
});
this function's code is not clear
function getNewWindowCorner(){
data.windowWidth = parseInt($els.window.width());
data.windowHeight = parseInt($els.window.height());
}
just see windowWidth & windowHeight potion
var data = {
"UPSContainer": {
"height" : 100,
"width" : 100
},
"isAnimating" : false
};
data has been declared as object and it has property like height, width & isAnimating etc but how we can add two new property called windowWidth & windowHeight to data object ??
just seeing the below code it seems that we can add any property to any object with any name at runtime in javascript and here we are storing value to windowWidth & windowHeight property.
data.windowWidth = parseInt($els.window.width());
data.windowHeight = parseInt($els.window.height());
so just see my whole code and tell me from where these two property comes windowWidth & windowHeight ? thanks
EDIT 1
Need bit more help. what it is called in js var $els = [];? is it array or object? what is the difference between var $els = []; and var els = {}; ? if this is array var $els = []; then how one can push anything into array like this way $els.window = $(window); or $els.body = $('body');. please help me understand the usage with small sample. thanks
For normal ones you can add them on the fly. They don't have to be declared from the start with the object. If they are they'll only be overwritten.
So you could either add everything you want from the start...
var data = {
"UPSContainer": {
"height": 100,
"width": 100
},
"isAnimating": false
};
.. or create it as you go
var data = {};
data.UPSContainer = {};
data.UPSContainer.height = 100;
data.UPSContainer.width = 100;
data.isAnimating = false;
data.windowWidth = parseInt($els.window.width());
data.windowHeight = parseInt($els.window.height());
it seems that we can add any property to any object with any name at runtime in javascript
Yes. You can. You just assign the new values.
where these two property comes windowWidth & windowHeight
From the code you are asking about. The assignment creates those properties.
In ECMAscript3 and ECMAScript5 , any property can be added to any object,
either by dot assignment, or through an array type notation.
data.windowWidth = parseInt($els.window.width());
or
data['windowWidth'] = parseInt($els.window.width());
create 'windowWidth' property for the data object.
In ECMA5 , this behaviour can be altered by following function:
Object.preventExtensions( obj )
and you can use Object.isExtensible( obj ) to check the current behaviour of that object.
If you try adding property to such an object for which extensions have been prevented, you would get an error in strict mode.
For your second question, in javascript array is also an object having properties , date is also an object , hence you can add properties to the array.
I have this function for adding a new item to the beginning of the list and removing the last one:
function addItem(id, text){
var el = $('#' + id);
var w = el.width();
el.css({
width: w,
overflow: 'hidden'
});
var ulPaddingLeft = parseInt(el.css('padding-left'));
var ulPaddingRight = parseInt(el.css('padding-right'));
el.prepend('<li>' + text + '</li>');
var first = $('li:first', el);
var last = $('li:last', el);
var fow = first.outerWidth();
var widthDiff = fow - last.outerWidth();
var oldMarginLeft = first.css('margin-Left');
first.css({
marginLeft: 0 - fow,
position: 'relative',
left: 0 - ulPaddingLeft
});
last.css('position', 'relative');
el.animate({ width: w + widthDiff }, 1500);
first.animate({ left: 0 }, 250, function() {
first.animate({ marginLeft: oldMarginLeft }, 1000, function() {
last.animate({ left: ulPaddingRight }, 250, function() {
last.remove();
el.css({
width: 'auto',
overflow: 'visible'
});
});
});
});
}
How can I make it work the other way around ? I want to add the item to the end and remove the first and also make it slide the other way around, like right to left.
Take a look at jQuery.append (and jQuery.prepend for beginning of list)
Your code seems really complicated. Simplifying it a little bit might give you something like this:
$("#whateverList").addItem("awesome")
jQuery.fn.addItem = function(text) {
var $li = $("<li>").text(text)
$(this).find("li:first").remove()
$(this).append($li)
}
jQuery plugin syntax is super easy to understand
append() to go to the bottom
var declarations at the top
Good luck!
Is it possible to highlight text inside of a textarea using javascript? Either changing the background of just a portion of the text area or making a portion of the text selected?
Try this piece of code I wrote this morning, it will highlight a defined set of words:
<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>
This was written for another post (http://facebook.stackoverflow.com/questions/7497824/how-to-highlight-friends-name-in-facebook-status-update-box-textarea/7597420#7597420), but it seems to be what you're searching for.
Easy script I wrote for this: Jsfiddle
OPTIONS:
Optional char counter.
Highlight several patterns with different colors.
Regex.
Collect matches to other containers.
Easy styling: fonts color and face, backgrounds, border radius and lineheight.
Ctrl+Shift for direction change.
//include function like in the fiddle!
//CREATE ELEMENT:
create_bind_textarea_highlight({
eleId:"wrap_all_highlighter",
width:400,
height:110,
padding:5,
background:'white',
backgroundControls:'#585858',
radius:5,
fontFamilly:'Arial',
fontSize:13,
lineHeight:18,
counterlettres:true,
counterFont:'red',
matchpatterns:[["(#[0-9A-Za-z]{0,})","$1"],["(#[0-9A-Za-z]{0,})","$1"]],
hightlightsColor:['#00d2ff','#FFBF00'],
objectsCopy:["copy_hashes","copy_at"]
//PRESS Ctrl + SHIFT for direction swip!
});
//HTML EXAMPLE:
<div id="wrap_all_highlighter" placer='1'></div>
<div id='copy_hashes'></div><!--Optional-->
<div id='copy_at'></div><!--Optional-->
Have Fun!
Improved version from above, also works with Regex and more TextArea fields:
<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.
$("#container0").highlight({
words: [["hello","hello"],["world","world"],["(\\[b])(.+?)(\\[/b])","$1$2$3"]],
width: 500,
height: 125,
count:0
});
$("#container1").highlight({
words: [["hello","hello"],["world","world"],["(\\[b])(.+?)(\\[/b])","$1$2$3"]],
width: 500,
height: 125,
count: 1
});
});
// 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.options.count);
this.inputContainer = this.element.find('#inputContainer'+this.options.count);
this.textarea = this.inputContainer.find('textarea');
this.highlighter = this.highlighterContainer.find('#highlighter'+this.options.count);
// apply the css
this.element.css({'position':'relative',
'overflow':'auto',
'background':'none repeat scroll 0 0 #FFFFFF',
'height':this.options.height+2,
'width':this.options.width+19,
'border':'1px solid'
});
// 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',
'z-index': '1'
});
this.inputContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '0px solid #000000',
'z-index': '2',
'background': 'none repeat scroll 0 0 transparent'
});
// 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
var isWebKit = navigator.userAgent.indexOf("WebKit") > -1,
isOpera = navigator.userAgent.indexOf("Opera") > -1,
isIE /*#cc_on = true #*/,
isIE6 = isIE && !window.XMLHttpRequest; // Despite the variable name, this means if IE lower than v7
if (isIE || isOpera){
var padding = '6px 5px';
}
else {
var padding = '5px 6px';
}
this.highlighter.css({
'padding': padding,
'color': '#eeeeee',
'background-color': '#ffffff',
'margin': '0px',
'font-size': '11px' ,
'line-height': '12px' ,
'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',
'width': this.options.width,
'height': this.options.height,
'font-size': '11px',
'line-height': '12px' ,
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif',
'overflow': 'hidden',
'border': '0px solid #000000'
});
// 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());
});
scope.applyText(this.textarea.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,' ',' ');
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][0],'<span style="background-color: #D8DFEA;">'+this.options.words[i][1]+'</span>');
//text = this.replaceAll(text,'(\\[b])(.+?)(\\[/b])','<span style="font-weight:bold;background-color: #D8DFEA;">$1$2$3</span>');
}
// re-inject the processed text into the div
this.highlighter.html(text);
if (this.highlighter[0].clientHeight > this.options.height) {
// document.getElementById("highlighter0")
this.textarea[0].style.height=this.highlighter[0].clientHeight +19+"px";
}
else {
this.textarea[0].style.height=this.options.height;
}
} 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="container0">
<div id="highlighterContainer0">
<div id="highlighter0"></div>
</div>
<div id="inputContainer0">
<textarea id="text1" cols="30" rows="15">hello world</textarea>
</div>
</div>
<h1> haus </h1>
<div id="container1">
<div id="highlighterContainer1">
<div id="highlighter1"></div>
</div>
<div id="inputContainer1">
<textarea cols="30" rows="15">hipp hipp
hurra,
[b]ich hab es jetzt![/b]</textarea>
</div>
</div>
</body>