TweetFollow Us on Twitter

Learning to Tango

Volume Number: 15 (1999)
Issue Number: 10
Column Tag: WebTech

Learning to Tango

by Ron Davis, Pervasive Software
Contributing Editor, John Daub

Dynamic web sites in no time

These days everybody has a web site. They start out as a single ugly page of text and gradually grow into a monster web of hyperlinks. Somewhere along the line of this evolution the person creating the site starts to think, "There's got to be a better way." Well, it turns out there is a better way: Tango.

Tango is a web application builder and server. It consists of two parts: The Developer Studio where you create your Tango Application Files (TAF) and the Tango Server you hook up to your web server to actually serve the TAFs. TAFs are files that contain instructions for doing a series of Actions. Actions are things you want to happen to create a web page, such as accessing databases, logic based on arguments, variable or cookies, or sending an e-mail message.

TAFs are uploaded to your web site. When a user requests a URL that refers to a file ending with the .taf extension, the TAF file is "executed". This means the Tango plug-in or CGI interprets the TAF, going through its logic and doing the actions stored in it, and then outputting HTML that is passed back to the user's web browser.

In this article you are going to actually create some TAF files and execute them via a web browser and server. If you want to do the examples, you will need to make sure Tango is set up correctly. Read the documentation for details on how to do this.

Note that with the exception of the description of the Project tab of the workspace window, all of the code in this article is based on Tango 3.6.

The Tango Server

Let's talk a minute about how the Tango Server works. Pervasive doesn't make an HTTP server; instead the software integrates with a number of other web servers. This is done in one of two ways on the Mac, either through a WebStar plug-in or through the Tango CGI. The WebStar plug-in supports StarNine's WebStar plug-in API, so it will work with other Mac web servers that support this API, like Quid Pro Quo. The CGI works with a number of other web servers, including personal web sharing which is built into Mac OS 8.x. TAF files created on the Mac can also be deployed to web servers on Windows and Solaris. In Tango 2000 these TAF files are XML.

The main difference between these two methods is what a URL that refers to a TAF looks like. Using the plug-in, the web server knows how to handle .taf files, so the URL looks pretty normal.

www.mactech.com/home.taf

If you are using the CGI you have to explicitly say that in the URL, so it looks like this:

www.mactech.com/$tango.acgi?home.taf

For the rest of this article it will be assumed you are using the plug-in and the "$tango.acgi?" part of the URL will be left out.

No matter which method you use to access a TAF file, the server handles doing all of the things you've coded into the file using the Developer Studio. The Tango Server is very robust. Tango is used to run the Jokes.com (http://www.jokes.com/) web site. This web site gets 8 million hits per month and sends out 10,000+ e-mail messages a day. Tango also serves news for The Globe.com (http://www.theglobe.com/), a national ISP.

The Developer Studio

The Developer Studio is where you develop your web application. Here is a quick tour of the Tango Editor. When you open the Tango Editor application you will be presented with the Workspace window, Figure 1. The Workspace contains tools and information that are application wide and that you will use throughout your development of TAF files. In Tango 3.6 there are three tabs: Project, Data Sources, and Snippets. Tango 2000 adds a fourth tab: Objects.


Figure 1.The Workspace Window

The Project Tab

Tango, just like CodeWarrior and a variety of other development environments, supports Projects. A Project is a collection of elements that are used in one design. In Tango 2000 these include:

  • Files, which are the TAF files in the project.
  • Presentations Pages, which are the equivalent of a C #include file.
  • Data Sources, which are databases that are used in the project.
  • Objects, which are other executable code modules that are called from the TAF.
  • Sites, which are FTP directories where you deploy your web site.

You can only directly change the Files folder and the Sites folder. The contents of the other folders are determined by what you reference in the various Actions used in your TAF files.

The Data Sources Tab

In Tango, all databases are called Data Sources. You can connect to a data source via a number of different methods, each of which has a folder in the Data Sources tab. They are DAM, the Data Access Manager, ODBC for connecting to SQL databases, and FileMaker for accessing FileMaker Pro databases via AppleEvents.

Before a database can be accessed from a TAF, you must create a Data Source for it.

The Snippets Tab

Tango supports the idea of snippets, which are little pieces of text you can add to lots of places in Tango via drag and drop or by double-clicking. Most of the snippets in the folders in the Snippets tab are read only, but you can add your own to the "My Snippets" folder.

The Objects Tab

New to Tango2000 is the ability to call code modules from inside a TAF. In the case of the Macintosh these code modules are either Java Beans or Tango Class Files (TCF). TCFs are like TAFs, but have an object interface to them.

Obviously, this is a very shallow overview of the workspace window. You can read the documentation that comes with Tango for more details, and you'll learn by doing the examples in this article.

Tango Application Files

Tango Application Files are the heart of Tango. It is here you create the dynamic nature of your web site. You are going to learn about these files by doing. If you are in the Tango editor create a new TAF file from the File menu. You'll get an empty TAF window that looks like Figure 2.


Figure 2.A new TAF window

In Tango you create code by dragging a series of Actions into the TAF window. If it isn't already open, go to the Views menu and select the Actions Palette.


Figure 3.The Actions palette

Each of the icons on this palette represents a different type of action. If you run your pointer over the icons the name of the action will be displayed under the icons. To add an action you drag it off the palette and into the TAF where you want it. Let's create a simple TAF to show just how easy it is to create an interactive web site with Tango.

First drag an If action into the TAF window. When you do, the action will open a window like this.


Figure 4.If Action window.

There is a lot of flexibility in this action, but we're going to keep it simple. The cursor is currently in the first Value column, so go ahead and type in "<@ARG _function>". Then tab twice to leave the = sign the same and get to the other value column. Type in "Mom". Now close the window.

What have you just done? You created an if statement that is going to check for a passed in Argument named _function and evaluate to True if it equals Mom. Tango has its own set of HTML like tags that can be inserted into various parts of Tango, including if statements and normal HTML. All of these tags start with "<@" and end with ">". The word "ARG" denotes an argument to this TAF. There are a lot more of these tags referred to as MetaTags in Tango.

So what is Tango going to do if the If statement is true? Right now nothing, but lets fix that. A Results Action allows you it insert strait HTML into the dynamic page you are creating. You can also include Tango MetaTags which are interpreted by the server prior to adding them to the output HTML. Drag in a Results Action. When you drag it under the If it will be indented unless you work at getting it to go to the left.

The Results Action window pops up for you to edit. Here we want to insert some HTML that will be displayed to the user if <@ARG _function> is equal to "Mom". Type in the HTML in Listing 1 and close the window.

Listing 1: Mom page HTML.
<HTML>
<TITLE>Mom's Page</TITLE>
<BODY>
Hi Mom!
</BODY>
</HTML>

Now we need to handle the non-Mom case. Drag an Else Action into the TAF, below the Result Action but at the same level as the If Action. Then drag in another Result Action under the else. Type the HTML from Listing 2 into the Result window and close it.

Listing 2: NonMom page HTML.

<HTML>
<TITLE>NonMom's Page</TITLE>
<BODY>
Hi Non Mom!
</BODY>
</HTML>

You've now written your first Tango Application. Save it as "parents.taf" and put it where your web server is going to find it and point your browser to it with a URL like this <http://www.yourserver.com/parents.taf>.

Your browser should display something like this:


Figure 5.NonMom page in browser.

Now I want to show you how arguments are passed. Change the URL to <http://www.yourserver.com/parents.taf?_function=Mom>. Executing that you will get a completely different page.


Figure 6.Mom page in browser.

Now you can see how to pass arguments manually in the URL, but that doesn't look very useful. Let us see a couple of ways this could be used. First, you could include the URL with argument into a hyperlink. Add the following line to the Non-mom result HTML.

	<A HREF="<@CGI><@APPFILE>?_function=Mom">Visit Mom</A>

Save you file and reload it in your browser. You'll now see a hyperlink on the page. Clicking on it will take you to the Mom page. Let's look for a moment at what we added. You'll notice the place where you would put the URL contains the cryptic "<@CGI><@APPFILE>". From the <@ notation you probably figured out these are Tango MetaTags, but what do they mean? These two tags create a URL to the TAF file currently be run.

The <@CGI> will insert the notation needed to execute via the CGI interface we talked about at the beginning of the article if you are running the CGI. It inserts nothing if you are using the plugin. It is a good thing to always include <@CGI> even if you never intend to use the CGI, because you might need to one day and or you might want to give your TAF to someone who does.

The <@APPFILE> tag inserts a path to the current file. You don't have to figure out relative links and such, and you don't have to change a bunch of HTML if you move the file.

Another way arguments get passed around is via forms. When a form is processed it creates arguments based on the values of the various controls and passes them to the action file when the Submit button is pressed. You're not going to get to see an example of that right here because we've milked this simple example as far as it will go, but we are moving to a new more complicated example, so watch for it.

Tango and Databases

Having logic and a means of passing information from one page to another is enough to make Tango cool for the web developer, but those abilities just scratching the surface. You can do all kinds of interesting things like sending e-mail, or executing an AppleScript. But the ability that really makes web sites dynamic and shows off the abilities of Tango is how it works with databases.

For this example you are going to create a simple user management system for a web site. Users will be able to sign up for the web site, selecting a username and password. This information will be entered into a database along with assigning a minimal user level. Then you'll create a TAF that allows you the administrator to change a user's information or delete them.

Creating a FileMaker Pro Data Source

To start off we need to create a database to hold the users. Tango supports a number of databases. For this article you can use FileMaker Pro. Launch file maker and create a new database with three fields, username of type text, password of type text, and userlevel of type number.

Once you have the database created you need to create a new Data Source in Tango to access the data base. With FileMaker still running, go to Tango and select he menu Data Source->New->FileMaker. You will be presented with a dialog to select the FileMaker application. For this example just use the default, which is "Any FileMaker application" and click OK. You will next be asked to select a database. Assuming you named your database UserDB your dialog will look like Figure 7. Select UserDB and click OK.


Figure 7.Select FileMaker Pro database dialog.

Next you will be asked to name your data source. Just name it the default, which is the same thing the database was named.


Figure 8.Select a Data Source name dialog.

Now you have a new Data Source in the Data Source panel of the Workspace window. Expand the disclosure triangles and you will see the layout of the database. FileMaker creates a number of secret fields. One is the Layout 0, which is an invisible layout. Also each layout has an invisible record_id field. You will avoid working with either of these for this example.

The New Record Builder

Now we can start working with the database. The first thing we need to do is create a way of adding a new user to the database. Tango offers two powerful tools for creating a bunch of code to do the two most common database tasks, adding a new record and searching a database via a TAF. The New Record Builder helps you add new records to the database and the Search Builder helps you search for records and change or delete them.

Create a new TAF called "newuser.taf". In the actions palette, drag a New Record Builder into the new TAF. You get a window that allows you to configure this builder. To create a page to allow us to add a new user we need to tell the builder which columns we want to create. To do this we drag those columns from the Data Source panel to the Columns area of the builder. Drag over username, password and userlevel from Layout#1.

You can set various options for each column as well. In your case you want the default behavior for the username and password fields, but you want a fixed value for the userlevel field. So select just the userlevel column in the builder. On the right side of the builder you get options for this column. Click the Fixed value radio button. You can popup the Value popup and see some of the things you could enter here. Right now leave the value popup on "Value Entered" and then type "1" into the text box. You are now done with the builder and it should look like Figure X. Click the Build and Close button to save your changes to the TAF.


Figure 9.New Record Builder.

Suddenly there is a bunch of code in your TAF file. You might want to look at the code to see what it does, but for now just know it works. You can save the TAF file and run it in your browser. You can enter a username and password into the form and hit Save. You'll get a message that the record was added. If you switch over to FileMaker, you will find that there is a new record in the database with the username and password you entered.

The Search Builder.

Using just the New Record Builder you created the means to add new users to your web site in about 2 minutes. Now you need to administrate these users. You need to be able to delete users and change their information. With Tango this is almost as easy by using Tango's other builder the Search Builder.

Create a new TAF called "adminusers.taf". In the editor drag a Search Builder from the actions palette into the TAF window. You'll be confronted with the Search Builder window. The Search Builder window is more complicated than the New Record Builder, but is still very useful and easy once you understand all of the things it can do.

The Search Builder creates a series of pages for you to select information from. First it creates a form to allow the user to enter criteria to search the database on. Then it creates a page with the results of the search at a high level. Each item on this "Record List" page is a hyperlink to more in-depth information that can be edited on the "Details Page".

For your user database you will create a search by user name only. Then you can display a list of user names and user levels of the results, and the details page will allow you to edit all of the columns of the table.

Take the username column in the Data Sources and drag it into the Columns panel of the Search tab in the Search Builder window. The right side of the builder window allows you to manipulate options for the search, such as whether to find items that begin with what's entered in the field, or contained anywhere in the string. You can also choose something other than an edit field for entry. You could even just have a fixed value for the search and skip the form field all together. By the way, if you skip entering anything in the search section it will find all of the records in your database.


Figure 10.Search Builder Search panel.

Click the Records List panel. FileMaker Pro does not support Joins so those sub panels are grayed out in all of the Search Builder panels. Here we are going to define what we see when Tango displays the results of the search. You want to show the user name and the user level of each of the results. To do this simply drag those two columns from the Data Sources into the Display Columns section of the search builder.

You'll also want to list the results by user name so drag the username column into the "Order By" panel on the bottom of the window. You'll notice you can set the number of records that are shown per page as well. Go ahead and leave the default values for this and the column display at the top.


Figure 11.Search Builder Record List panel.

Clicking over to the Record Details panel you get to configure what fields you will be able to edit in individual records. In this example you are going to edit them all, so drag username, password and userlevel over to the builder.

This time you are going to be changing some of the Column Options for editing. Select all of your columns in the builder and click the Allow Update check box. You will now be able to edit all of the fields. You also want to be able to delete users so check the "Allow delete of record from:" check box in the Record Options section. Since you have only one table you don't need to change the popup.


Figure 12.Search Builder Details panel.

Click the "Build & Close" button to generate the TAF file. Again a bunch of code was generated, and it would be a good learning experience for you to look through the various actions and see what is being done.

Test your TAFs by using the newsuser.taf file to add a few users. Use these names: admin, bubba, bubbette, leroy, and alfred.

Run the adminusers.taf file. You'll see a form with one field, Username, and two buttons Find and Reset Values. Click the Find button without entering any user name. Your results should look like Figure 13. This is a listing of all of the records in the database.


Figure 13.Results of searching for all records.

Click on the admin link. You will now see the details page, which will allow you to change various columns. Change the admin's user level to 10, and click save. In the page that tells you the record was successfully changed click the link to search again. You might want to do another empty search again to see that the admin changed.

At the search page, enter "bub" into the search. You'll get back results for "bubba" and "bubbette". It turns out these are the same person and you don't want multiple accounts per user, so we want to get rid of the bubbette account. The results of this search only show "bubba" and "bubbette". Click bubbette and delete her from the Details page.

The Log-in TAF

There is just one more aspect of our member system we need to implement, the ability to log in. Create a new TAF we are going to name "login.taf". What you need to do is create a form for the user to enter their username and password, then you will see if that user is in the database and if they have the right password. Then you want to in some way be able to tell if a user is logged in when they go to another page. In this case we will use a cookie.

If you have looked at any of the code the Builders built you will find the common TAF coding practice of using the _function argument to control what part of a TAF is executed. You will use that in the login.taf file as well. So the first thing you need to add to the TAF is an If action. You want to make the condition be like Figure 14.


Figure 14.If Action.

Drag a Result action below and inside the If action. Result actions are html code that is put straight into the HTML returned to the Browser. In this case the HTML will define the log in form. Enter the following code.

Listing 3: Login page ResultsHTML.

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<HTML>
<HEAD>
<TITLE>Login</TITLE>
</HEAD>
<BODY>

<FORM ACTION="<@CGI><@APPFILE>?_function=search" METHOD=POST>
<TABLE BORDER="0">
	<TR>	
		<TD>Username:</TD>
		<TD>
			<INPUT TYPE="text" NAME="username">
		</TD>
	</TR>
	<TR>	
		<TD>Password</TD>
		<TD>
			<INPUT TYPE="password" NAME="password">
		</TD>
	</TR>
</TABLE>
<INPUT TYPE=SUBMIT VALUE="Search"> <INPUT TYPE=RESET VALUE="Reset Values">
</FORM>

</BODY>
</HTML>

Look at a couple of things in this form. First the FORM ACTION is a POST method and the URL for the action is the current file. In that URL you've set _function to be "search" which will allow us to branch correctly. Also realize that each of the input tags will be passed as arguments with the name given them in the <INPUT> tag.

You need to add an ElseIf to login.taf. Then set the criteria to check that <@ARG _function> is equal to "search". This will cause the ElseIf's code to be executed when the form's submit button is pressed.

To test if the user entered valid data into the log in form we need to search the user database, so add a Search action to the ElseIf in login.taf You need to select the username and password, so drag them into the Selected Columns area. Now click over to the criteria tab. You only want to find the records of the database that are the same as the entered information. To do this, you drag columns into the criteria table and set what you want the criteria to be. In this case you want to make sure the username argument and the password argument are the same as the username and password columns in the database.

Drag in the username and password columns from the Data Sources. Edit the criteria so it looks like Figure 15. Notice you want to set the criteria Incl. Empty to be true. If you don't do this, there will be no search on empty fields. That means you could leave the password blank and always log in.


Figure 15.Login Search Action window.

After the Search comes back you need to handle the two possibilities. First, the search may return no records because the user isn't in the database or their password was wrong. Second, the Search will return a record for the user. What you will do is check the results using actions in the TAF.

Drag an If action under the Search action, making sure it is level with the Search and not the ElseIf. Anytime you do a search certain variables are created and set. One of those variables is <@NUMROWS>, which is the number of database table rows that were returned by the search. If <@NUMROWS> is greater than zero you found a valid username and password in the Search. In our new If action check to see if <@NUMROWS> is greater than zero.


Figure 16. If <@NUMROWS> Action.

To handle the logged in correctly case, you are going to set a variable of the type cookie that will indicate the user is logged in. We do this using an Assign action. Drag an Assign action under the If action. Click in the first column of the action window and set the scope to cookie. Set the name in the next column to "loggedin" and set the value to "true". Once this is set you can ask for the variable named loggedin with the scope of cookie at the top of each page. If it is not there or not equal to true the user isn't logged in. Also realize variables time out in Tango if they are not used, so eventually the user will have to log in again.

The last thing to do is to handle the case where they logged in wrong. This is a simple Results action that tells them they screwed up and offers a link back to the log in page. Here's the HTML for the result action.

Listing 4: Invalid Login ResultsHTML.

Invalid username or password.
<P>
<A HREF="<@CGI><@APPFILE>?_function=login">Log in again.</A>

That is the basics of a user management system using Tango. If you did this in a traditional CGI language like Perl, AppleScript, or PHP it would take you a lot longer. In Tango it could be done in an afternoon at the most.

There are a lot of things this example leaves out, but it is an example and not a full system. It shows you some of the powerful things you can do with Tango in a short period of time and gives you a start toward a real user management system. If you want to explore Tango more using this example try adding the following features. Let the user Log-out, this would involve setting the cookie variable to be invalid. Also explore what would happen if the user tried to log-in twice. Make it so you can't log in twice.

You've now taken the first steps in learning to Tango, and you need to get out on the dance floor and practice. Hopefully from the examples in this article you have a good idea of the power of Tango.

If you want to learn more about Tango go to the Pervasive web site. In addition to a lot of useful information, Pervasive will be putting out pre-releases of Tanogo2000 for the Mac that you can download and see all of the new features for this next release. You also want to check out the URLs in the bibliography to see some of the other online Tango resources.

Bibliography

Sites that use Tango:

Ron Davis <rdavis@pervasive.com> is a Senior Software Engineer at Pervasive Software in Austin, Texas. He works on the Macintosh version of the Developer Studio. In his spare time he creates a Tango-based web site for reviewing science fiction. The fact this site isn't public yet reflects how much free time he has.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Tokkun Studio unveils alpha trailer for...
We are back on the MMORPG news train, and this time it comes from the sort of international developers Tokkun Studio. They are based in France and Japan, so it counts. Anyway, semantics aside, they have released an alpha trailer for the upcoming... | Read more »
Win a host of exclusive in-game Honor of...
To celebrate its latest Jujutsu Kaisen crossover event, Honor of Kings is offering a bounty of login and achievement rewards kicking off the holiday season early. [Read more] | Read more »
Miraibo GO comes out swinging hard as it...
Having just launched what feels like yesterday, Dreamcube Studio is wasting no time adding events to their open-world survival Miraibo GO. Abyssal Souls arrives relatively in time for the spooky season and brings with it horrifying new partners to... | Read more »
Ditch the heavy binders and high price t...
As fun as the real-world equivalent and the very old Game Boy version are, the Pokemon Trading Card games have historically been received poorly on mobile. It is a very strange and confusing trend, but one that The Pokemon Company is determined to... | Read more »
Peace amongst mobile gamers is now shatt...
Some of the crazy folk tales from gaming have undoubtedly come from the EVE universe. Stories of spying, betrayal, and epic battles have entered history, and now the franchise expands as CCP Games launches EVE Galaxy Conquest, a free-to-play 4x... | Read more »
Lord of Nazarick, the turn-based RPG bas...
Crunchyroll and A PLUS JAPAN have just confirmed that Lord of Nazarick, their turn-based RPG based on the popular OVERLORD anime, is now available for iOS and Android. Starting today at 2PM CET, fans can download the game from Google Play and the... | Read more »
Digital Extremes' recent Devstream...
If you are anything like me you are impatiently waiting for Warframe: 1999 whilst simultaneously cursing the fact Excalibur Prime is permanently Vault locked. To keep us fed during our wait, Digital Extremes hosted a Double Devstream to dish out a... | Read more »
The Frozen Canvas adds a splash of colou...
It is time to grab your gloves and layer up, as Torchlight: Infinite is diving into the frozen tundra in its sixth season. The Frozen Canvas is a colourful new update that brings a stylish flair to the Netherrealm and puts creativity in the... | Read more »
Back When AOL WAS the Internet – The Tou...
In Episode 606 of The TouchArcade Show we kick things off talking about my plans for this weekend, which has resulted in this week’s show being a bit shorter than normal. We also go over some more updates on our Patreon situation, which has been... | Read more »
Creative Assembly's latest mobile p...
The Total War series has been slowly trickling onto mobile, which is a fantastic thing because most, if not all, of them are incredibly great fun. Creative Assembly's latest to get the Feral Interactive treatment into portable form is Total War:... | Read more »

Price Scanner via MacPrices.net

Early Black Friday Deal: Apple’s newly upgrad...
Amazon has Apple 13″ MacBook Airs with M2 CPUs and 16GB of RAM on early Black Friday sale for $200 off MSRP, only $799. Their prices are the lowest currently available for these newly upgraded 13″ M2... Read more
13-inch 8GB M2 MacBook Airs for $749, $250 of...
Best Buy has Apple 13″ MacBook Airs with M2 CPUs and 8GB of RAM in stock and on sale on their online store for $250 off MSRP. Prices start at $749. Their prices are the lowest currently available for... Read more
Amazon is offering an early Black Friday $100...
Amazon is offering early Black Friday discounts on Apple’s new 2024 WiFi iPad minis ranging up to $100 off MSRP, each with free shipping. These are the lowest prices available for new minis anywhere... Read more
Price Drop! Clearance 14-inch M3 MacBook Pros...
Best Buy is offering a $500 discount on clearance 14″ M3 MacBook Pros on their online store this week with prices available starting at only $1099. Prices valid for online orders only, in-store... Read more
Apple AirPods Pro with USB-C on early Black F...
A couple of Apple retailers are offering $70 (28%) discounts on Apple’s AirPods Pro with USB-C (and hearing aid capabilities) this weekend. These are early AirPods Black Friday discounts if you’re... Read more
Price drop! 13-inch M3 MacBook Airs now avail...
With yesterday’s across-the-board MacBook Air upgrade to 16GB of RAM standard, Apple has dropped prices on clearance 13″ 8GB M3 MacBook Airs, Certified Refurbished, to a new low starting at only $829... Read more
Price drop! Apple 15-inch M3 MacBook Airs now...
With yesterday’s release of 15-inch M3 MacBook Airs with 16GB of RAM standard, Apple has dropped prices on clearance Certified Refurbished 15″ 8GB M3 MacBook Airs to a new low starting at only $999.... Read more
Apple has clearance 15-inch M2 MacBook Airs a...
Apple has clearance, Certified Refurbished, 15″ M2 MacBook Airs now available starting at $929 and ranging up to $410 off original MSRP. These are the cheapest 15″ MacBook Airs for sale today at... Read more
Apple drops prices on 13-inch M2 MacBook Airs...
Apple has dropped prices on 13″ M2 MacBook Airs to a new low of only $749 in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, now available for $679 for 8-Core CPU/7-Core GPU/256GB models. Apple’s one-year warranty is included, shipping is free, and each... Read more

Jobs Board

Seasonal Cashier - *Apple* Blossom Mall - J...
Seasonal Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Seasonal Fine Jewelry Commission Associate -...
…Fine Jewelry Commission Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) Read more
Seasonal Operations Associate - *Apple* Blo...
Seasonal Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Read more
Hair Stylist - *Apple* Blossom Mall - JCPen...
Hair Stylist - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.